package com.walt.zhong.sample.views

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.SweepGradient
import android.util.AttributeSet
import android.util.Log
import android.view.View
import com.walt.zhong.sample.R
import java.lang.Integer.min

class RadarScanView : View {
    private var drawing: Boolean = false
    private val mPaintBackground: Paint by lazy {
        Paint().apply {
            isAntiAlias = true
            style = Paint.Style.STROKE
        }
    }

    private val mPaintLine: Paint by lazy {
        Paint().apply {
            color = Color.parseColor("#3CBEAE")
            isAntiAlias = true
            strokeWidth = 1f
            style = Paint.Style.STROKE
        }
    }

    private val mPaintCircle: Paint by lazy {
        Paint().apply {
            color = Color.WHITE
            isAntiAlias = true
        }
    }

    private val mPaintScan: Paint by lazy {
        Paint().apply {
            style = Paint.Style.FILL_AND_STROKE
        }
    }

    private var mDiameter: Int = 0

    private var mRadius: Int = 0

    private lateinit var mRect: Rect

    private val mMatrix by lazy {
        android.graphics.Matrix()
    }

    private var mCurrentScanRotateAngle: Int = 0

    private val mBackgroundMipmap = BitmapFactory.decodeResource(resources, R.drawable.rader)

    private var mCenterBitmap: Bitmap =
        BitmapFactory.decodeResource(resources, R.drawable.circle_photo)

    private val mCircleProportions: Array<Float> =
        arrayOf(1 / 13f, 2 / 13f, 3 / 13f, 4 / 13f, 5 / 13f, 6 / 13f)

    private var mScanRotateSpeed = 5

    private var mCurrentScanCount: Int = 0

    private var mMaxScanItemCount: Int = 1

    private var mCurrentScanItem: Int = 0

    private var mScan: Boolean = false

    private lateinit var mListener: IScanListener

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )

    init {
        drawing = true
        keepScreenOn = true
        // 设置在触摸模式下此视图是否可以接收焦点。将其设置为true也将确保该视图可聚焦。
        isFocusableInTouchMode = true

    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        drawing = true
        post(object : Runnable {
            override fun run() {
                if (drawing) {
                    calc()
                    invalidate()
                    postDelayed(this, 10)
                } else {
                    removeCallbacks(this)
                }
            }
        })
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        drawing = false
    }

    private fun calc() {
        mCurrentScanRotateAngle = (mCurrentScanRotateAngle + mScanRotateSpeed) % 360
        mMatrix.postRotate(mScanRotateSpeed.toFloat(), mRadius.toFloat(), mRadius.toFloat())
        // 开始扫描显示标志为 true 且 只扫描一周
        if (mScan && mCurrentScanCount <= (360 / mScanRotateSpeed) && ::mListener.isInitialized) {
            if (mCurrentScanCount % mScanRotateSpeed == 0 && mCurrentScanItem < mMaxScanItemCount) {
                mListener.onScanning(mCurrentScanItem, mCurrentScanRotateAngle)
                mCurrentScanItem++
            }
            if (mCurrentScanItem == mMaxScanItemCount) {
                mListener.onScanSuccess()
            }
            mCurrentScanCount++
        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        // 测量
        setMeasuredDimension(getMeasureSize(widthMeasureSpec), getMeasureSize(heightMeasureSpec))
    }

    /**
     * 获取尺寸
     *
     * @param measureSpec Int
     * @return Int
     */
    private fun getMeasureSize(measureSpec: Int): Int = run {
        val specMode = MeasureSpec.getMode(measureSpec)
        val specSize = MeasureSpec.getSize(measureSpec)
        if (specMode == MeasureSpec.EXACTLY) specSize else {
            // 指定测量大小
            if (specMode == MeasureSpec.AT_MOST) min(300, specSize) else 300
        }
    }

    /**
     * 当视图的大小发生变化时，这个方法会在布局过程中调用
     *
     * @param w Int
     * @param h Int
     * @param oldw Int
     * @param oldh Int
     */
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        mDiameter = min(w, h)
        mRadius = mDiameter / 2
        mRect = Rect(
            (mRadius - mDiameter * mCircleProportions[0]).toInt(),
            (mRadius - mDiameter * mCircleProportions[0]).toInt(),
            (mRadius + mDiameter * mCircleProportions[0]).toInt(),
            (mRadius + mDiameter * mCircleProportions[0]).toInt()
        )
        Log.d("zhongxj", "onSizeChanged: ====>w：$w mRadius：$mRadius mDiameter：$mDiameter")
    }

    /**
     * 在这个方法内进行重绘界面的操作
     *
     * @param canvas Canvas
     */
    override fun onDraw(canvas: Canvas) {
        // 绘制的层级由调用的先后顺序决定，先绘制的在下面，后绘制的在上面
        drawBackground(canvas)
        drawCircle(canvas)
        drawScan(canvas)
        drawCenterIcon(canvas)
    }

    /**
     * 绘制背景
     *
     * @param canvas Canvas
     */
    protected fun drawBackground(canvas: Canvas) {
        canvas.drawBitmap(mBackgroundMipmap, 0f, 0f, mPaintBackground)
    }

    /**
     * 绘制圆线圈
     *
     * @param canvas Canvas
     */
    private fun drawCircle(canvas: Canvas) {
        canvas.run {
            for (i in 1..5) {
                drawCircle(
                    mRadius.toFloat(),
                    mRadius.toFloat(),
                    mDiameter * mCircleProportions[i],
                    mPaintLine
                )
            }
        }
    }

    /**
     * 绘制扫描部分
     *
     * @param canvas Canvas
     */
    private fun drawScan(canvas: Canvas) {
        canvas.run {
            save()
            // 只赋值一次，避免在重绘时重复创建对象
            if (mPaintScan.shader == null) {
                mPaintScan.shader = SweepGradient(
                    mRadius.toFloat(), mRadius.toFloat(),
                    intArrayOf(Color.TRANSPARENT, Color.parseColor("#84B5CA")),
                    null
                )
            }
            concat(mMatrix)
            drawCircle(
                mRadius.toFloat(), mRadius.toFloat(), mDiameter * mCircleProportions[4],
                mPaintScan
            )
            restore()
        }
    }

    /**
     * 绘制中间的圆形图标
     *
     * @param canvas Canvas
     */
    private fun drawCenterIcon(canvas: Canvas) {
        canvas.drawBitmap(mCenterBitmap, null, mRect, mPaintCircle)
    }
}

interface IScanListener {
    fun onScanning(position: Int, scanAngle: Int)

    fun onScanSuccess()
}